# 元祖
# 由一系列变量组成的不可变序列容器。不可变是指一但创建，不可以再添加/删除/修改元素。
# 元组特点：元组使用小括号，且逗号隔开各个数据，数据可以是不同的数据类型，和列表一样都是有顺序的。

# 总结
# 优势：元组轻量、不可变，适合存储固定数据（如配置项、坐标等）。
# 注意：若需修改数据，应使用列表；若需哈希（如字典键），必须用元组。


# 1. 下标和切片： 查找、截取操作
# 2. index函数：返回指定数据所在位置的下标 。
# 3. count函数：统计指定数据在当前列表中出现的次数。
# 4. len函数（内置的）：访问列表长度，即列表中数据的个数。
# 5. for循环遍历

# 1. 元组创建
# 空元组
# empty_tuple = ()
# t1 = tuple()

# 单元素元组（需加逗号）
# single_elem = (42,)  # 注意：不加逗号会被识别为整数
# print(single_elem)

# 多元素元组
# t2 = (1, "hello", 3.14, True)
# t3 = tuple([1, 2, 3])  # 从列表转换
# print(t1)
# print(t2)
# print(t3)


# 2. 元组访问与切片
# t = (10, 20, 30, 40, 50)
# 索引访问
# print(t[0])  # 输出: 10
# print(t[-1])  # 输出: 50（倒数第一个元素）
# 切片操作
# print(t[1:3])  # 输出: (20, 30)（左闭右开区间）
# print(t[:2])  # 输出: (10, 20)


# 3. 元组不可变性
# 元组一旦创建，元素不可修改，但可以重新赋值整个元组：
t = (1, 2, 3)
# t[0] = 100  # 报错：TypeError
# print(id(t)) # 输出 1958305432896
# 重新赋值
# t = (100, *t[1:])  # 输出: (100, 2, 3)
# print(id(t)) # 输出 1958305495680 地址变了

# 4. 元组解包与扩展
# 解包赋值
# a, b, c = (1, 2, 3)
# print(a, b, c)  # 输出: 1 2 3
# 星号解包（Python3+）
# first, *rest, last = (1, 2, 3, 4, 5)
# print(rest)  # 输出: [2, 3, 4]（剩余部分转为列表）

# 5. 元组常用操作
print('*' * 30 + '  元组常用操作  ' + '*' * 30)

t = (1, 2, 2, 3)
# 长度
print(len(t))  # 输出: 4
# 计数与索引
print(t.count(2))  # 输出: 2（元素2出现的次数）
print(t.index(3))  # 输出: 3（元素3首次出现的索引）
# 合并元组
t_new = t + (4, 5)  # 输出: (1, 2, 2, 3, 4, 5)
print(t_new)


# 6. 元组与循环
print('*' * 30 + '  元组与循环  ' + '*' * 30)
# 遍历元组
for item in (1, 2, 3):
    print(item)
# 枚举遍历
for idx, val in enumerate(('a', 'b', 'c')):
    print(f"Index: {idx}, Value: {val}")

# 7. 元组与函数
# 元组常用于函数返回多个值或作为不可变参数传递：
print('*' * 30 + '  元组与函数  ' + '*' * 30)


def get_coordinates():
    return (3.5, 7.2)


x, y = get_coordinates()  # 解包函数返回值
print(x, y)

# 8. 元组与生成器
# 生成器表达式可生成元组：
print('*' * 30 + '  元组与生成器  ' + '*' * 30)
gen = (x**2 for x in range(9))
t = tuple(gen)  # 输出: (0, 1, 4)
print(t)
# 总结
# 优势：元组轻量、不可变，适合存储固定数据（如配置项、坐标等）。
# 注意：若需修改数据，应使用列表；若需哈希（如字典键），必须用元组。